import { AxiosPromise, AxiosRequestConfig, AxiosResponse } from "../type";
import { createError } from "./helpers/error";
import { parseHeaders } from "./helpers/headers";

/**
 * 逻辑处理
 */
export default function xhr(config: AxiosRequestConfig): AxiosPromise {
  return new Promise((resolve, reject) => {
    const { data = null, url, method = 'get', headers, responseType,timeout} = config;

    // 创建 XMLHttpRequest 异步对象
    const request = new XMLHttpRequest();
    
    // 响应时间
    if(timeout) request.timeout = timeout

    request.ontimeout = function() {
      // reject(new Error(`Timeout of ${timeout} ms exceeded`));
      reject(createError(
        `Timeout of ${timeout} ms exceeded`,
        config, 
        "TIMEOUT",
        request
      ))
    };

    // 配置请求参数
    request.open(method.toUpperCase(), url, true);

    // 请求头处理
    Object.keys(headers).forEach(name => {
      if (data === null && name.toLowerCase() === 'content-type') {
        delete headers[name];
      }
      request.setRequestHeader(name, headers[name]);
    })

    if (responseType) {
      request.responseType = responseType;
    }

    // 发送请求
    request.send(data);

    // 注册事件,拿到响应信息
    request.onreadystatechange = function handleLoad() {
      if (request.readyState !== 4) return;
      if (request.status === 0)  return;

      const responseHeaders = parseHeaders(request.getAllResponseHeaders());

      const responseData = responseType && responseType !== 'text' ? request.response : request.responseText;

      const response: AxiosResponse = {
        data: responseData,
        status: request.status,
        statusText: request.statusText,
        headers: responseHeaders,
        config,
        request
      };
      handleResponse(response);
    }
    
    request.onerror = function() {
      // reject(new Error("Net Error"));
      reject(createError(
        "net error",
        config, 
        null,
        request
      ))
    };

    function handleResponse(response: AxiosResponse): void{
      if(response.status >= 200 && response.status <300) {
        resolve(response)
      }else{
        reject(
          createError(
              `Request failed with status code ${response.status}`,
               config,
               null,
               request.status,
               response
          )
      );
      }
    }
  })
}